import type { PropType } from 'vue'
import { defineComponent, toRaw, useAttrs, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import type { MenuItem } from './types'
import './style.less'

export default defineComponent({
  props: {
    // 导航菜单的数据
    data: {
      type: Array as PropType<MenuItem[]>,
      // required: true,
    },
    dynamicRoutes: {
      type: Array as PropType<RouteRecordRaw[]>,
      default: () => [],
    },
    // 菜单标题的键名
    name: {
      type: String,
      default: 'name',
    },
    // 菜单标识的键名
    index: {
      type: String,
      default: 'index',
    },
    // 菜单图标的键名
    icon: {
      type: String,
      default: 'icon',
    },
    // 菜单子菜单的键名
    children: {
      type: String,
      default: 'children',
    },
  },
  setup(props) {
    const attrs = useAttrs()
    const route = useRoute()
    const router = useRouter()
    const selectedKeysMap: any = {}
    const openKeysMap: any = {}
    // const menuData = getMenuData(toRaw(constantRoutes), [], '')
    const menuData = getMenuData(toRaw(props.dynamicRoutes), [], '')
    let selectedKeys = selectedKeysMap[route.path]
    let openKeys = openKeysMap[route.path]

    // 封装一个渲染无限层级菜单的方法
    // 函数会返回一段jsx的代码
    const renderMenu = (data: any[]) => {
      return data.map((item: any) => {
        // 每个菜单的图标
        // item.i = (Icons as any)[item[prop.icon!]]
        item.i = item.meta?.icon
        // 处理sub-menu的插槽(父菜单的title)
        const slots = {
          title: () => {
            return (
              <>
                <item.i />
                <span>{item.name}</span>
              </>
            )
          },
        }
        // 递归渲染children
        if (item.children && item.children.length) {
          return (
            <a-sub-menu key={item.path} v-slots={slots}>
              {renderMenu(item.children)}
            </a-sub-menu>
          )
        }
        // 正常渲染普通的菜单
        return (
          <a-menu-item key={item.path}>
            <item.i />
            <span>{item.name}</span>
          </a-menu-item>
        )
      })
    }

    // 路由到菜单的映射
    function getMenuData(
      routes: RouteRecordRaw[] = [],
      parentKeys: string[] = [],
      selectedKey = '',
    ): any {
      const menuData = []
      for (const item of routes) {
        openKeysMap[item.path] = parentKeys // 当前对象上的所有父节点都打开
        selectedKeysMap[item.path] = [selectedKey || item.path]
        if (item.name && !item.hideInMenu) {
          const newItem = { ...item }
          // 过滤更新children的值
          delete newItem.children
          if (item.children && !item.hideChildrenInMenu) {
            // 随着递归从最深处慢慢往外退出收集path赋值给parentKeys
            newItem.children = getMenuData(item.children, [
              ...parentKeys,
              item.path,
            ], '')
          }
          else {
            // 当有隐藏的时候--照样映射keysMap
            getMenuData(
              item.children!,
              selectedKey ? parentKeys : [...parentKeys, item.path],
              selectedKey || item.path,
            )
          }
          menuData.push(newItem)
        }
        else if (!item.hideInMenu && !item.hideChildrenInMenu && item.children) {
          // 没有name的情况--返回的数组进行解构成一个个对象
          menuData.push(
            ...getMenuData(item.children, [...parentKeys, item.path], ''),
          )
        }
      }
      return menuData
    }

    watch(
      () => router.currentRoute.value.path,
      (val: any) => {
        selectedKeys = selectedKeysMap[val]
        openKeys = openKeysMap[val]
      },
    )

    return () => {
      return (
        <a-menu
          class="side-menu-container"
          selectedKeys={selectedKeys}
          openKeys={openKeys}
          mode="inline"
          theme="dark"
          {...attrs}
        >
          {renderMenu(menuData)}
        </a-menu>
      )
    }
  },
})
